package com.motu.vertx.module.utility.webtool;


import com.motu.vertx.module.utility.kafka.KafkaLogManager;
import com.motu.vertx.module.utility.mysql.MysqlTool;
import com.motu.vertx.module.utility.mysql.MysqlUtils;
import com.motu.vertx.module.utility.postgresql.PostgreUtils;
import com.motu.vertx.module.utility.redis.RedisTools;
import com.motu.vertx.module.utility.threadpool.DBLogManager;
import com.motu.vertx.module.utility.toolset.ErrorWord;
import com.motu.vertx.module.utility.toolset.ErrorWordManager;
import com.motu.vertx.module.utility.toolset.TimeUtils;
import com.motu.vertx.module.utility.toolset.Tool;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.jdbc.JDBCClient;
import io.vertx.ext.sql.SQLClient;
//import io.vertx.ext.sync.Sync;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.Session;
import io.vertx.ext.web.client.HttpResponse;
import io.vertx.ext.web.client.WebClient;
import io.vertx.sqlclient.Pool;
import io.vertx.redis.client.RedisAPI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

//import com.motu.chaosweb.web.DbLogThread;
//import com.motu.chaosweb.web.MainVerticle;
//import com.motu.redis.RedisKey;
//import io.vertx.ext.web.client.WebClient;


public class BaseWebHandler {
	public static final String commonWebPath = "com.motu.vertx.module.utility.webhandler.";
	private static final Logger logger = LoggerFactory.getLogger(BaseWebHandler.class);
	protected static final int TOKEN_EXPIRE_TIME = 86400*7;//有效期两天
	protected static final int TOKEN_ACCESS_TIME = 3600;//redis存储时间(即检查时间)
	public static void sendHttpResponse(HttpServerResponse response,JsonObject result){
		if(!result.containsKey("ret")){
			result.put("ret", 0);
		}
		response.putHeader("content-type", "application/text; charset=utf-8")
		.end(result.toString());
		logger.debug("sendHttpResponse :"+result.toString());
	}
	public static void sendHttpResponseError(HttpServerResponse response,String errMsg){
		JsonObject result = new JsonObject();
		result.put("ret", 1);
		result.put("errmsg",errMsg);
		response.putHeader("content-type", "application/text; charset=utf-8")
		.end(result.toString());
	}
	public static void sendHttpResponseError(HttpServerResponse response,ErrorWord er,String errMsg){
		JsonObject result = new JsonObject();
		result.put("ret", er.value);
		result.put("errmsg",errMsg);
		response.putHeader("content-type", "application/text; charset=utf-8")
		.end(result.toString());
	}
	public static void sendHttpResponseError(HttpServerResponse response,ErrorWord er){
		JsonObject result = new JsonObject();
		result.put("ret", er.value);
		result.put("errmsg",ErrorWordManager.get("CMD_DEFAULT", er, 0));
		response.putHeader("content-type", "application/text; charset=utf-8")
		.end(result.toString());
	}
	/***
	 * 缓存中登录验证及权限判断
	 * @param routingContext
	 * @param role
	 * @return
	 */
	public static Future<JsonArray> checkUserLogin2(RoutingContext routingContext, String role, RedisAPI redisClient, String redisKey, Pool jdbcClient){
		Promise<JsonArray> fut = Promise.promise();
		JsonObject json = routingContext.body().asJsonObject();
		String token = json.getString("token");
		String user = json.getString("user");
		//		String key = RedisKey.getWebUserTokenKey(user);
		RedisTools.getHashJsonObject(redisKey, res->{
			JsonObject obj = res.result();
			if(res == null || obj.isEmpty()){
				//				fut.fail("error");
				//				sendHttpResponseError(routingContext.response(), "token错误");
				Future<JsonArray> fut2 = checkTokenFromDB(routingContext, role, user, token,redisClient,redisKey,jdbcClient);
				fut2.onComplete(fut);
			}else{
				try {
					//				if(token.equalsIgnoreCase(obj.getString("token"))){
					long tokenTime = Long.parseLong(obj.getString("tokentime"));
					//					logger.info("###redis token user:"+user+" token:"+token+" obj:"+obj.toString()+" tokenTime:"+Tool.getTimeFullStr(tokenTime));
					long timeDiff = TimeUtils.getTimeDiff(tokenTime);
					if(timeDiff > TOKEN_EXPIRE_TIME){
						logger.info("###redis token expire user:"+user+" token:"+token+" tokenTime:"+TimeUtils.getTimeFullStr(tokenTime)+" timeDiff:"+timeDiff+" redisKey:"+redisKey);
						fut.fail("error");
						sendHttpResponseError(routingContext.response(),ErrorWord.TOKEN_EXPIRED, "token过期");
					}else{
						String rolelist = obj.getString("rolelist");
						if(role != null){

							JsonArray array = new JsonArray(rolelist);
							if(!array.contains(role)){
								fut.fail("error");
								sendHttpResponseError(routingContext.response(), "权限不足");
							}else{
								fut.complete();
							}
						}else{
							fut.complete();
						}
//					JsonObject robj = new JsonObject().put("token", token).put("tokentime", obj.getString("tokentime")).put("rolelist", rolelist.toString());
//					RedisTools.setHashJsonObject(redisClient, redisKey, robj);
//					RedisTools.expire(redisClient, redisKey, TOKEN_EXPIRE_TIME);
					}
					//				}else{
					//					//从数据库再查询一次，如果跟数据库一致，那也让校验通过（预留）
					////					fut.fail("error");
					////					sendHttpResponseError(routingContext.response(), "token错误");
					//					Future<JsonArray> fut2 = checkTokenFromDB(routingContext, role, user, token,redisClient,redisKey,jdbcClient);
					//					fut2.onComplete(fut.completer());
					//				}
				} catch (Exception e) {
					logger.error("checkUserLogin2 error !!! user:" + user + " token :" + token + " error:"+e.getMessage());
					fut.fail("error");
				}

			}
		});
		return fut.future();
	}
	/***
	 * 从数据库中校验token，并校验权限
	 * @param routingContext
	 * @param role 接口权限限制
	 * @param user 账号名
	 * @param token
	 * @return 判断结果
	 */
	private static Future<JsonArray> checkTokenFromDB(RoutingContext routingContext,String role,String user,String token,RedisAPI redisClient,String redisKey, Pool jdbcClient){
		Promise<JsonArray> fut = Promise.promise();
		String sql = "SELECT a.tokentime,b.enable FROM manager_token a , manager_users b where a.username = b.username and a.username = ? and a.token = ?;";
		JsonArray params = new JsonArray();
		params.add(user);
		params.add(token);
		MysqlTool.queryJsonArrayFromDb(jdbcClient, sql, params,handler->{
			if(handler.succeeded()){
				JsonArray array  = handler.result();
				if(array.size() > 0){
					JsonObject obj = array.getJsonObject(0);
					int tokenTime = obj.getInteger("tokentime");
					long timeDiff = TimeUtils.getTimeDiff(tokenTime);
					if( obj.getInteger("enable") == 0) {
						RedisTools.del(redisKey);
						fut.fail("error");
						sendHttpResponseError(routingContext.response(), "该用户被禁止登录，请联系管理员！");
					}else if(timeDiff > TOKEN_EXPIRE_TIME){
						sendHttpResponseError(routingContext.response(),ErrorWord.TOKEN_EXPIRED, "dbtoken过期");
					}else{
						JsonArray params2 = new JsonArray();
						params2.add(user);
						String sql2 = "SELECT role FROM manager_roles where username = ?;";
						MysqlTool.queryJsonArrayFromDb(jdbcClient, sql2, params2,handler2->{
							if(handler2.succeeded()){
								JsonArray array2  = handler2.result();
								JsonArray roleList = new JsonArray();
								for(int i=0;i<array2.size();i++){
									roleList.add(array2.getJsonObject(i).getString("role"));
								}
//								logger.info("### user:"+user+" roleList:"+roleList.toString());
								if(role != null){
									if(!roleList.contains(role)){
										fut.fail("error");
										sendHttpResponseError(routingContext.response(), "db权限不足");
									}else{
										fut.complete();
									}
								}else{
									fut.complete();
								}
								long curTime = TimeUtils.getCurTime();
								String key = redisKey;//RedisKey.getWebUserTokenKey(user);
								JsonObject robj = new JsonObject().put("token", token).put("tokentime",curTime).put("rolelist", roleList.toString());
								robj.put("checktime", TimeUtils.getCurTime()); //检测时间
								RedisTools.setHashJsonObject(key, robj);
								RedisTools.expire(key, TOKEN_ACCESS_TIME);
								String sql3 = "update manager_token set tokentime = ? where username = ? and token = ?;";
								JsonArray params3 = new JsonArray();
								params3.add(curTime);
								params3.add(user);
								params3.add(token);
								MysqlTool.updateToDb(jdbcClient, sql3, params3, handler3->{});
							}else{
								fut.fail("error");
								sendHttpResponseError(routingContext.response(), handler2.cause().getMessage());
							}

						});
					}
					//					}
				}else{
					logger.error("###database token wrong mysql:"+sql+" params:"+params.toString());

					fut.fail("error");
					sendHttpResponseError(routingContext.response(),ErrorWord.TOKEN_WRONG, "token错误！");
				}
			}else{
				fut.fail("error");
				sendHttpResponseError(routingContext.response(), handler.cause().getMessage());
			}
		});
		return fut.future();
	}
	/***
	 * 普通登录和扫码登录的回调
	 * @param resArray
	 * @return
	 */
	public static void loginCallback(RoutingContext context,Pool jdbcClientWeb,RedisAPI redisClient,String username,JsonArray resArray){
		HttpServerRequest req = context.request();
		HttpServerResponse response = context.response();
		Session session = context.session();		
		int id = resArray.getJsonObject(0).getInteger("id");
		String webperms = resArray.getJsonObject(0).getString("webperms");
		String gameperms = resArray.getJsonObject(0).getString("gameperms");
		String bigames = resArray.getJsonObject(0).getString("bigames");
		String relation = resArray.getJsonObject(0).getString("relation");
		String platform = resArray.getJsonObject(0).getString("platform");
		String channel = resArray.getJsonObject(0).getString("channel");
		String gmname = resArray.getJsonObject(0).getString("gmname");
		int depid = resArray.getJsonObject(0).getInteger("depid");
		int groupid = resArray.getJsonObject(0).getInteger("groupid");
		int employeeid = resArray.getJsonObject(0).getInteger("employeeid");
		int accounttype = resArray.getJsonObject(0).getInteger("account_type");
		String feishu_info = resArray.getJsonObject(0).getString("feishu_info");

		if (session != null) {
			session.regenerateId();
			String sql_role = "select role from manager_roles where username = ?;";  //角色列表
			String sql_group = "select projectid, refuselist from webpages_group where groupid = ?;";//group资源限制
			String sql_username = "select projectid, refuselist from webpages_username where username = ?;";//user资源限制
			String sql_perms = "select id,projectid,isgameserver from webtype"; //游戏服务器权限列表
			String projectidString = "";
			if(gameperms != null&& !gameperms.isEmpty()) {
				//去重 获取projectid
				String[] tmp = gameperms.split(",");
				for (int i=0 ; i < tmp.length ;i ++) {
					String[] itmp = tmp[i].split("-");
					if( projectidString.indexOf(itmp[0]) == -1) {
						if(projectidString != "") {
							projectidString += ",";
						}
						projectidString += itmp[0];
					}
				}
				sql_perms += " where projectid in ("+projectidString+");";//游戏服务器权限列表(projectid)
			}else {
				sql_perms += " where false;";//列表为空，没有权限，不查询出数据
			}
			 							
			JsonArray paramgroup = new JsonArray().add(groupid);
			JsonArray paramsusername = new JsonArray().add(username);
			Future<JsonArray> fut_role = MysqlTool.queryJsonArrayFromDb(jdbcClientWeb, sql_role, paramsusername);
			Future<JsonArray> fut_group = MysqlTool.queryJsonArrayFromDb(jdbcClientWeb, sql_group, paramgroup);
			Future<JsonArray> fut_username = MysqlTool.queryJsonArrayFromDb(jdbcClientWeb, sql_username, paramsusername);
			Future<JsonArray> fut_perms = MysqlTool.queryJsonArrayFromDb(jdbcClientWeb, sql_perms, new JsonArray());
			Future.all(fut_role, fut_group, fut_username,fut_perms).onComplete(ar->{
				if (ar.succeeded()) {
					JsonArray rolelist = new JsonArray();   //角色列表
					for(int i=0; i<fut_role.result().size();i++){
						rolelist.add(fut_role.result().getJsonObject(i).getString("role"));
					}
					
					JsonArray webpages = fut_group.result();   //资源限制列表，合并fut_group,fut_username结果
					JsonArray webpages_username = fut_username.result();
					for (int k=0; k<webpages_username.size(); k++) {
						webpages.add(webpages_username.getJsonObject(k));
					}
					JsonArray gamepermsArray = new JsonArray();  //允许访问的游戏服务器类型
					if(gameperms != null&& !gameperms.isEmpty()) {
						for (String i  : gameperms.split(",")) {
							gamepermsArray.add(i);
						}
					}
					
					JsonArray permArray = new JsonArray();  //允许访问的后台列表
					if(webperms != null&& !webperms.isEmpty()) {
						String webpermsTmp = webperms;
						webpermsTmp = webpermsTmp.replace("[","");
						webpermsTmp = webpermsTmp.replace("]","");
						JsonArray permlist = fut_perms.result();
																		
						//gameperms权限整合
						if(gamepermsArray.size() != 0) {  
							for (int i=0; i<permlist.size();i++ ) {
								JsonObject tmp = permlist.getJsonObject(i);
								String tmpString = tmp.getInteger("projectid") + "-" + tmp.getInteger("isgameserver");
								if(gameperms.indexOf(tmpString) != -1 && webpermsTmp.indexOf(tmp.getInteger("id").toString()) == -1 ) {
									webpermsTmp += ",";
									webpermsTmp += tmp.getInteger("id");
								}
							}
						}		
						webpermsTmp = "[" + webpermsTmp + "]";
						permArray = new JsonArray(webpermsTmp);
					}

					JsonArray bigamesArray = new JsonArray();  //允许访问的bi游戏列表
					if(bigames != null&& !bigames.isEmpty()) {
						bigamesArray = new JsonArray(bigames);
						
					}
					JsonArray relationArr = new JsonArray();  //账号关联者列表
					if (relation != null && !relation.isEmpty()) {
						relationArr = new JsonArray(relation);
					}
					JsonObject result = new JsonObject();
					result.put("success", true);
//					String token = context.getCookie("vertx-web.session").getValue();
					String token = context.session().value();

					result.put("id",id);
					result.put("token",token);
					result.put("rolelist", rolelist);
					result.put("webpages", webpages);
					result.put("webperms", permArray);
					result.put("gameperms", gamepermsArray);
					result.put("bigames", bigamesArray);
					result.put("relation", relationArr);
					result.put("platform", platform);
					result.put("channel", channel);
					result.put("depid", depid);
					result.put("employeeid", employeeid);
					result.put("name", username);
					result.put("gmname", gmname);
					result.put("accounttype", accounttype);
					result.put("isHaveFeishuInfo", !Tool.isEmpty(feishu_info));

					sendHttpResponse(response, result);
					
					//更新reidis里的登录信息，更新touken
					String key = RedisTools.getWebUserTokenKey(username,token);
					JsonObject obj = new JsonObject().put("tokentime", TimeUtils.getCurTime());
					obj.put("checktime", TimeUtils.getCurTime()); //检测时间
					obj.put("rolelist", rolelist.toString());
					obj.put("webperms", permArray.toString());
					obj.put("bigames", bigamesArray.toString());
					RedisTools.setHashJsonObject(key, obj);
					RedisTools.expire( key,TOKEN_ACCESS_TIME);
					String sql = "insert into manager_token(username,token,tokentime) values(?,?,?);";
					JsonArray params = new JsonArray().add(username).add(token).add(TimeUtils.getCurTime());
					MysqlTool.updateToDb(jdbcClientWeb, sql, params, res1->{
						if (res1.succeeded()) {
							int a = 0;
							logger.info("###loginCallback update redis success user:"+username+" token:"+token);
						}else{
							logger.error("###loginCallback update redis error user:"+username+" token:"+token+" error:"+res1.cause().getMessage());
						}
					});
				} else {
					sendHttpResponseError(response, ar.cause().getMessage());
				}
			});
		}
	}
	private static void updateTokenTime(){
	}
	/***
	 * 获取数据库列字段拼接
	 * @param array
	 * @return
	 */
	protected static String getColumnsString(JsonArray array){
		String str = "";
		for(int k=0;k<array.size();k++){
			str += array.getString(k);
			if(k != array.size()-1){
				str += ",";
			}
		}
		return str;
	}
	/***
	 * 获取列表
	 * @param routingContext
	 * @param jdbcClient
	 * @param tableName
	 */
	public static void getTableList(RoutingContext routingContext, Pool jdbcClient, String tableName){
		HttpServerResponse response = routingContext.response();

		String sql1 = "select count(1) from "+tableName+";";
		MysqlTool.queryJsonArrayFromDb(jdbcClient, sql1,new JsonArray() , handler1->{
			if(handler1.succeeded()){
				JsonArray list1 = handler1.result();
				if(list1 != null&&list1.size() > 0){
					int total = list1.getJsonObject(0).getInteger("count(1)");
					JsonObject json = routingContext.body().asJsonObject().getJsonObject("pdata");
					String columns = "*";
					if(json.containsKey("columns")){
						columns = getColumnsString(json.getJsonArray("columns"));

					}
					String sortColumn = "id desc";//默认按id排序
					if(json.containsKey("orderby")){
						sortColumn = json.getString("orderby");
					}
					String sql = "select "+columns+" FROM "+tableName+"  order by "+sortColumn+"  limit ?,?;";
					JsonArray params = new JsonArray();

					int pageNo = json.getInteger("pageNo");
					int pageSize = json.getInteger("pageSize");
					int start = pageNo*pageSize;
					params.add(start);
					params.add(pageSize);
					MysqlTool.queryJsonArrayFromDb(jdbcClient, sql,params , handler->{
						if(handler.succeeded()){
							JsonArray list = handler.result();
							JsonObject result = new JsonObject();
							result.put("total", total);
							result.put("rows",list);
							sendHttpResponse(response, result);
						}else{
							logger.error(handler.cause().getMessage());
							sendHttpResponseError(response, "数据库查询失败，请稍后重试！");
						}
					});
				}else{
					sendHttpResponseError(response, "数据库查询失败1，请稍后重试！");
				}
			}else{
				logger.error(handler1.cause().getMessage());
				sendHttpResponseError(response, "数据库查询失败，请稍后重试！");
			}
		});
	}
	/***
	 * 插入一条数据，并返回http请求的结果
	 * @param routingContext
	 * @param jdbcClient
	 * @param tableName
	 * @param jsonDecrypt
	 * @return
	 */
	public static Future<Long> addToTable(RoutingContext routingContext,Pool jdbcClient,String tableName,JsonObject jsonDecrypt){
		Promise<Long> fut = Promise.promise();
		HttpServerResponse response = routingContext.response();
		JsonObject json = jsonDecrypt != null?jsonDecrypt:routingContext.body().asJsonObject().getJsonObject("pdata");
		Iterator<Entry<String, Object>> it = json.iterator();
		JsonArray params = new JsonArray();
		String keys = "";
		String values = "";
		while(it.hasNext()){
			Entry<String, Object> en = it.next();
			keys += en.getKey();
			values += "?";
			if(it.hasNext()){
				keys += ",";
				values += ",";
			}
			params.add(en.getValue());
		}

		//		logger.debug("keys:"+keys+" values:"+values);
		String sql = "insert into "+tableName+"("+keys+") values("+values+"); ";
		MysqlTool.insertAndGetID(jdbcClient, sql, params, handler->{
			if(handler.succeeded()){
				Long res =  handler.result();//只返回插入后的自增值而已
				JsonObject result = new JsonObject();
				if(res != null ){//如果有自增值再取
					long id = res;
					result.put("id", id);
					fut.complete(id);
				}
				sendHttpResponse(response, result);
				sendLog(routingContext, result);
			}else{
				logger.error(handler.cause().getMessage());
				sendHttpResponseError(response, handler.cause().getMessage());
				fut.complete((long) 0);
			}
		});
		return fut.future();
	}
	/***
	 * 插入一条数据
	 * @param json
	 * @param jdbcClient
	 * @param tableName
	 * @return 执行结果
	 */
	public static Future<Long> addToTable(JsonObject json, Pool jdbcClient,String tableName){
		Promise<Long> fut = Promise.promise();
		Iterator<Entry<String, Object>> it = json.iterator();
		JsonArray params = new JsonArray();
		String keys = "";
		String values = "";
		while(it.hasNext()){
			Entry<String, Object> en = it.next();
			keys += en.getKey();
			values += "?";
			if(it.hasNext()){
				keys += ",";
				values += ",";
			}
			params.add(en.getValue());
		}
		//		logger.debug("keys:"+keys+" values:"+values);
		String sql = "insert into "+tableName+"("+keys+") values("+values+"); ";
		MysqlTool.insertAndGetID(jdbcClient, sql, params, handler->{
			if(handler.succeeded()){
				Long res =  handler.result();//只返回插入后的自增值而已
				JsonObject result = new JsonObject();
				if(res != null ){//如果有自增值再取
					long id = res;
					result.put("id", id);
					fut.complete(id);
				}
			}else{
				logger.error(handler.cause().getMessage());
				fut.complete((long) 0);
			}
		});
		return fut.future();
	}
	/***
	 * 更新一条数据，并返回http请求结果
	 * @param routingContext
	 * @param jdbcClient
	 * @param tableName 表名
	 * @param jsonData 上行数据是否在外层被重新组装过
	 * @return 更新结果
	 */
	public static Future<Long> updateToTable(RoutingContext routingContext,Pool jdbcClient,String tableName,JsonObject jsonData){
		Promise<Long> fut = Promise.promise();
		HttpServerResponse response = routingContext.response();
		JsonObject json = jsonData != null?jsonData:routingContext.body().asJsonObject().getJsonObject("pdata");

		JsonArray params = new JsonArray();
		long id = json.getLong("id");
		json.remove("id");
		Iterator<Entry<String, Object>> it = json.iterator();
		String sql = "update "+tableName+" set ";
		while(it.hasNext()){
			Entry<String, Object> en = it.next();
			sql += en.getKey()+"=?";
			if(it.hasNext()){
				sql += ",";
			}
			params.add(en.getValue());
		}
		sql += " where id = ?;";
		params.add(id);
		logger.debug("sql:"+sql);
		MysqlTool.updateToDb(jdbcClient, sql, params, handler->{
			if(handler.succeeded()){
				int num = (Integer) handler.result();//更新的条数
				if(num == 1){
					JsonObject result = new JsonObject();

					sendHttpResponse(response, result);
					sendLog(routingContext, result);
					fut.complete(id);
				}else{
					fut.fail("更新失败：更新到"+num+"条数据！");
					sendHttpResponseError(response, "更新失败：更新到"+num+"条数据！");
				}
			}else{
				logger.error(handler.cause().getMessage());
				sendHttpResponseError(response, handler.cause().getMessage());
				fut.fail(handler.cause().getMessage());
			}
		});
		return fut.future();
	}
	/***
	 * 更新数据，并返回一个异步结果
	 * @param jdbcClient
	 * @param tableName 表名
	 * @param json 上行数据
	 * @return 更新结果
	 */
	public static Future<Long> updateToTable(Pool jdbcClient,String tableName,JsonObject json){
		Promise<Long> fut = Promise.promise();

		JsonArray params = new JsonArray();
		long id = json.getLong("id");
		json.remove("id");
		Iterator<Entry<String, Object>> it = json.iterator();
		String sql = "update "+tableName+" set ";
		while(it.hasNext()){
			Entry<String, Object> en = it.next();
			sql += en.getKey()+"=?";
			if(it.hasNext()){
				sql += ",";
			}
			params.add(en.getValue());
		}
		sql += " where id = ?;";
		params.add(id);
		logger.debug("sql:"+sql);

		MysqlTool.updateToDb(jdbcClient, sql, params, handler->{
			if(handler.succeeded()){
				//				fut.complete(id);
				int num = (Integer) handler.result();//更新的条数
				if(num == 1){
					fut.complete(id);
				}else{
					fut.fail("更新失败：更新到"+num+"条数据！");
				}
			}else{
				logger.error(handler.cause().getMessage());
				fut.fail(handler.cause().getMessage());
			}
		});
		return fut.future();
	}
	/***
	 * 插入一条数据日志，保存上下行的数据
	 * @param routingContext
	 * @param result 下行数据
	 */
	protected static void sendLog(RoutingContext routingContext,JsonObject result){
		String adminName = routingContext.body().asJsonObject().getString("user");
		String requestStr = routingContext.body().asJsonObject().getJsonObject("pdata").toString();
		String responseStr = result.toString();
		String apiStr = routingContext.request().uri();
		JsonArray params = new JsonArray();
		params.add(adminName);
		params.add(apiStr);
		params.add(requestStr);
		params.add(responseStr);
		params.add(TimeUtils.getCurTime());
		//		EventBus eventBus = MainVerticle.instance.vertxInstance.eventBus();
		JsonObject json = new JsonObject();
		String sql = "insert into webmanager_log(user,api,request,response,addtime) values(?,?,?,?,?)";
		json.put("sql", sql);
		json.put("params", params);
		KafkaLogManager.addGameLog(sql, params, DBLogManager.DBTYPE_SERVER);
		//		eventBus.send(Constant.EVENT_BUS_DB_SAVE_LOG, json);
	}
	/***
	 * 根据id获取一条数据
	 * @param routingContext
	 * @param jdbcClient
	 * @param tableName
	 */
	public static void getFromTable(RoutingContext routingContext,Pool jdbcClient,String tableName){
		JsonObject json = routingContext.body().asJsonObject().getJsonObject("pdata");
		getFromTable(routingContext,jdbcClient,tableName,json);
	}

	public static void getFromTable(RoutingContext routingContext,Pool jdbcClient,String tableName,JsonObject json){
		HttpServerResponse response = routingContext.response();
		long id = json.getLong("id");
		String sql = "select * FROM "+tableName+" where id = ?;";
		JsonArray params = new JsonArray();
		params.add(id);
		MysqlTool.queryJsonArrayFromDb(jdbcClient, sql, params, handler->{
			if(handler.succeeded()){
				JsonArray list = handler.result();
				if(list.size() == 1){
					JsonObject obj = list.getJsonObject(0);
					JsonObject result = new JsonObject();
					result.put("info",obj);
					sendHttpResponse(response, result);
				}else{
					sendHttpResponseError(response, "数据库查询失败，请输入有效的id！");
				}

			}else{
				logger.error(handler.cause().getMessage());
				sendHttpResponseError(response, handler.cause().getMessage());
			}
		});

	}
	/***
	 * 从表中删除数据
	 * @param routingContext
	 * @param jdbcClient
	 * @param tableName
	 * @return
	 */
	public static Future<JsonArray> deleteFromTable(RoutingContext routingContext, Pool jdbcClient, String tableName){
		JsonObject json = routingContext.body().asJsonObject().getJsonObject("pdata");
		return deleteFromTable(routingContext,jdbcClient,tableName,json);
	}

	public static Future<JsonArray> deleteFromTable(RoutingContext routingContext,Pool jdbcClient,String tableName,JsonObject json){
		Promise<JsonArray> fut = Promise.promise();
		HttpServerResponse response = routingContext.response();
		JsonArray idList = json.getJsonArray("ids");


		JsonArray params = new JsonArray();
		String sql = "delete from "+tableName+"  where id in (";
		for(int i = 0;i<idList.size();i++){
			sql += "?";
			if(i < idList.size()-1){
				sql += ",";
			}
			params.add(idList.getLong(i));
		}
		sql += ");";

		MysqlTool.updateToDb(jdbcClient, sql, params, handler->{
			if(handler.succeeded()){

				JsonObject result = new JsonObject();

				sendHttpResponse(response, result);
				sendLog(routingContext, result);
				fut.complete(idList);
			}else{
				logger.error(handler.cause().getMessage());
				sendHttpResponseError(response, handler.cause().getMessage());
				fut.complete(null);
			}
		});
		return fut.future();
	}

	/**
	 * 搜索数据，分页
	 * @param routingContext
	 * @param jdbcClient
	 * @param sql
	 * @param params
	 */
	public static  void searchFromTable(RoutingContext routingContext, JDBCClient jdbcClient, String sql, JsonArray params) {
		HttpServerResponse response = routingContext.response();
		MysqlUtils.queryJsonArrayFromDb(jdbcClient, sql, params, handler1->{
			if (handler1.succeeded()) {
				String sql2 = "select FOUND_ROWS() as total;";
				MysqlUtils.queryJsonArrayFromDb(jdbcClient, sql2, new JsonArray(), handler2->{
					if (handler2.succeeded()) {
						JsonObject result = new JsonObject();
						result.put("rows",handler1.result());
						result.put("total", handler2.result().getJsonObject(0).getInteger("total"));
						sendHttpResponse(response, result);
					} else {
						sendHttpResponseError(response,  handler2.cause().getMessage());
					}
				});
			} else {
				sendHttpResponseError(response,  handler1.cause().getMessage());
			}
		});
	}
	
	/***
	 * 搜索数据，旧接口
	 * @param routingContext
	 * @param jdbcClient
	 * @param tableName
	 * @param sql1
	 * @param params1
	 * @param sql2
	 * @param params2
	 */
	public static void searchFromTable(RoutingContext routingContext,Pool jdbcClient,String tableName,String sql1,JsonArray params1,String sql2,JsonArray params2){

//		logger.info("searchFromTable  sql1:"+sql1 +" param1:"+params1.toString());
//		logger.info("searchFromTable  sql2:"+sql2 +" param2:"+params2.toString());
		HttpServerResponse response = routingContext.response();


		Promise<JsonArray> futn = Promise.promise(); //定义最终的操作
		Promise<JsonArray> fut1 = Promise.promise();//定义第一个操作
		JsonObject result = new JsonObject();
		long startTime = System.currentTimeMillis();
		//使用compose示例 串行方式
		//		MysqlTool.queryJsonArrayFromDb(jdbcClient, sql1,params1,fut1.completer());//执行第一个查询

		//		fut1.compose(handler1-> {	
		//			logger.info("search "+(System.currentTimeMillis()-startTime)+"ms sql1:"+sql1 +" param1:"+params1.toString());
		//			int total = handler1.getJsonObject(0).getInteger("count(1)");
		//			result.put("total", total);
		//			if(total > 0){
		//				MysqlTool.queryJsonArrayFromDb(jdbcClient, sql2,params2, futn);//执行第二个查询
		//			}else{//如果第一个查询没有结果，则不需要再子查询
		//				futn.complete(new JsonArray());
		//			}
		//
		//		},futn);
		//
		//		futn.onComplete(handler->{//设置最终处理函数
		//			logger.info("search "+(System.currentTimeMillis()-startTime)+"ms sql2:"+sql2 +" param2:"+params2.toString());
		//			if(handler.succeeded() && handler.result() != null){
		//				JsonArray list = handler.result();
		//				result.put("rows",list);
		//				sendHttpResponse(response, result);
		//			}else{
		//				sendHttpResponseError(response,  handler.cause().getMessage());
		//			}
		//		});
		routingContext.vertx().executeBlocking(()->{
			//使用compose示例 并行方式
			MysqlTool.queryJsonArrayFromDb(jdbcClient, sql1,params1,fut1);//执行第一个查询
			MysqlTool.queryJsonArrayFromDb(jdbcClient, sql2,params2, futn);//执行第二个查询
			Future.all(fut1.future(),futn.future()).onComplete(res->{
				if(res.succeeded()) {
					int queryTime = (int)(System.currentTimeMillis()-startTime)/1000;

					int total = fut1.future().result().getJsonObject(0).getInteger("count(1)");
					result.put("total", total);
					JsonArray list = futn.future().result();
					result.put("rows",list);
					sendHttpResponse(response, result);
					if(queryTime >= 10 && tableName.startsWith("record_")) {//大于10秒的查询，打印一下
						recordQueryLongTime(jdbcClient, sql1, params1, sql2, params2, queryTime);
					}
				}else {
					int queryTime = (int)(System.currentTimeMillis()-startTime)/1000;
					sendHttpResponseError(response,  res.cause().getMessage());
					logger.error("####### searchFromTable error:"+res.cause().getMessage() + " -- queryTime:" + queryTime +  " --  sql1:" + sql1 + " params1:" + params1 + " sql2:" + sql2 + " params2:" + params2);
				}
			});
			return null;
		},false,r->{
			if(r.failed()) {
				logger.error("####### searchFromTable executeBlocking error:"+r.cause().getMessage());
			}
//			logger.info("####### searchFromTable complete time:"+(System.currentTimeMillis()-startTime)+"ms");
		});

	}
	public static void recordQueryLongTime(Pool jdbcClient,String sql1,JsonArray params1,String sql2,JsonArray params2,int queryTime) {
		String sql = "insert into log_query(sql1,params1,sql1_final,sql2,params2,sql2_final,querytime,addtime) values(?,?,?,?,?,?,?,?);";
		JsonArray params = new JsonArray();
		params.add(sql1);
		params.add(params1.toString());
		params.add(Tool.getSqlString(sql1, params1));
		params.add(sql2);
		params.add(params2.toString());
		params.add(Tool.getSqlString(sql2, params2));
		params.add(queryTime);
		params.add(TimeUtils.getCurTime());
		MysqlTool.updateToDb(jdbcClient, sql, params, handler->{});
	}
	
	/***
	 * 搜索一条数据，并取出关联的子表信息，如act和actdetail
	 * @param routingContext
	 * @param jdbcClient1
	 * @param sql1 
	 * @param params1
	 * @param jdbcClient2
	 * @param sql2
	 * @param params2
	 */
	public static void getOneWithDetail(RoutingContext routingContext,Pool jdbcClient1,String sql1,JsonArray params1,Pool jdbcClient2,String sql2,JsonArray params2){
		//		logger.debug("getOneWithDetail sql1:"+sql1 +" param1:"+params1.toString());
		//		logger.debug("getOneWithDetail sql2:"+sql2 +" param2:"+params2.toString());

		HttpServerResponse response = routingContext.response();


		Promise<JsonArray> futn =Promise.promise(); //定义最终的操作
		Promise<JsonArray> fut1 = Promise.promise();//定义第一个操作
		JsonObject result = new JsonObject();
		MysqlTool.queryJsonArrayFromDb(jdbcClient1, sql1,params1, fut1);//执行第一个查询
		fut1.future().onSuccess(handler1-> {
			JsonArray list = handler1;
			if(list.size() == 1){
				JsonObject obj = list.getJsonObject(0);
				result.put("info",obj);
				MysqlTool.queryJsonArrayFromDb(jdbcClient2, sql2,params2, futn);//执行第二个查询
			}else{
				futn.fail("数据库查询失败，请输入有效的id！");
			}
		}).onFailure(futn::fail);

		futn.future().onComplete(handler->{//设置最终处理函数
			if(handler.succeeded() && handler.result() != null){
				JsonArray list = handler.result();
				result.put("details",list);
				sendHttpResponse(response, result);
			}else{
				sendHttpResponseError(response, handler.cause().getMessage());
			}
		});

	}
	/***
	 * 根据搜索条件列表，拼接出sql语句
	 * @param scList 搜索条件列表
	 * @param json 客户端上行数据
	 * @param params sql参数列表
	 * @return sql语句部分
	 */
	protected static String getSearchString(List<SearchCondition> scList,JsonObject json,JsonArray params){
		String str = "";
		for(SearchCondition sc:scList){
			String key = sc.getJsonKey();
			if(json.containsKey(key)){
				str += " and ";
				String opr = sc.getOperator();
				String[] dbkeys = sc.getDbKeys();
				if(opr == "=" || opr == ">=" || opr == "<=" || opr == ">" || opr == "<"|| opr == "<>"){
					str += (dbkeys==null?key:dbkeys[0]) +" "+opr + " ? ";//如果跟数据库一致，就不需要指定dbkeys
					params.add(json.getValue(key));
				}else if(opr == "like"){
					str += "(";
					if(dbkeys == null){
						dbkeys = new String[]{key};//默认
					}
					for(int i=0;i<dbkeys.length;i++){
						if(i > 0){
							str +=" or ";
						}
						str += dbkeys[i]+" "+opr + " ? ";//如果跟数据库一致，就不需要指定dbkeys
						params.add("%"+json.getValue(key)+"%");
					}
					str += ")";
				}else if(opr == "in"){
					str += (dbkeys==null?key:dbkeys[0]) +" "+opr + "(";//如果跟数据库一致，就不需要指定dbkeys
					JsonArray ids = sc.getIds();
					for(int i=0;i<ids.size();i++){
						str += "?";
						if(i != ids.size() -1){
							str += ",";
						}
						params.add(ids.getValue(i));
					}
					str += ")";
				}
			}
		}
		return str;
	}
	/***
	 * 根据搜索条件列表，从表中搜索数据
	 * @param routingContext 
	 * @param jdbcClient
	 * @param json 客户端上行数据
	 * @param tableName 表名
	 * @param scList 搜索条件列表
	 */
	protected static void searchFromTable(RoutingContext routingContext,Pool jdbcClient,JsonObject json,String tableName,List<SearchCondition> scList){

		String sql1 = " FROM "+tableName+" where 1=1 ";
		JsonArray params1 = new JsonArray();
		String str1 = getSearchString(scList, json, params1);
		String sortColumn = "id desc";//默认按id排序
		if(json.containsKey("orderby")){
			sortColumn = json.getString("orderby");
		}
		sql1 += str1+" order by "+sortColumn;

		String sql = "select count(1) "+sql1+";";
		String columns = "*";
		if(json.containsKey("columns")){
			columns = getColumnsString(json.getJsonArray("columns"));

		}
		String sql2 = "select "+columns+" "+sql1+" limit ?,?; ";
		JsonArray params2 = params1.copy();
		int pageNo = json.getInteger("pageNo");
		int pageSize = json.getInteger("pageSize");
		int start = pageNo*pageSize;
		params2.add(start);
		params2.add(pageSize);
		searchFromTable(routingContext,jdbcClient, tableName, sql, params1, sql2, params2);
	}
	/***
	 * 添加一条操作日志
	 * @param userId 用户id
	 * @param adminName 用户名
	 * @param reason 操作理由
	 * @param operation 操作内容
	 */
	protected static void addGameUserLog(Pool jdbcClient,long userId,String adminName,String reason,String operation){
		String sql = "insert into webmanager_gameuser_log(userid,adminname,reason,operation,addtime) values(?,?,?,?,?); ";
		JsonArray params = new JsonArray();
		params.add(userId);
		params.add(adminName);
		params.add(reason);
		params.add(operation);
		params.add(TimeUtils.getCurTime());
		MysqlTool.updateToDb(jdbcClient, sql, params, handler->{
			if(handler.succeeded()){

			}else{
				logger.error(handler.cause().getMessage());
			}
		});
	}
	/***
	 * 根据id从数据库中查询一条
	 * @param json 前端的上传的数据
	 * @param jdbcClient 数据库接口
	 * @param tableName 表名
	 * @return 异步查询结果
	 */
	public static Future<JsonObject> getFromTable(JsonObject json,Pool jdbcClient,String tableName){
		Promise<JsonObject> fut = Promise.promise();
		long id = json.getLong("id");
		String sql = "select * FROM "+tableName+" where id = ?;";
		JsonArray params = new JsonArray();
		params.add(id);
		MysqlTool.queryJsonArrayFromDb(jdbcClient, sql, params, handler->{
			if(handler.succeeded()){
				JsonArray list = handler.result();
				if(list.size() == 1){
					JsonObject obj = list.getJsonObject(0);
					JsonObject result = new JsonObject();
					result.put("info",obj);
					fut.complete(result);
				}else{
					fut.fail("数据查询为空");
				}

			}else{
				logger.error(handler.cause().getMessage());
				fut.fail(handler.cause().getMessage());
			}
		});
		return fut.future();
	}
	/***
	 * 判断是否为公共的网页处理接口
	 * @param className 类名
	 * @return 判断结果
	 */
	public static boolean isCommonWebHandler(String className){
		String classNames[] = new String[]{"manager","acttype","badwords","crashlog","errorcode","gmaccount","param","recordlog","recordlog2","recordtype","serverreload","whitelist","feedback","banneduser","refund","incomemonitor","redistool","downlog"};
		for(int i=0;i<classNames.length;i++){
			if(className.equalsIgnoreCase(classNames[i])){
				return true;
			}
		}
		return false;
	}

	/***
	 * 获取客户端ip,如果经过ngnix转发，则取X-Real-IP参数得到真实ip
	 * @param routingContext
	 * @return
	 */
	public static String getClientIp(RoutingContext routingContext){
		return Tool.getClientIp(routingContext);
	}
	/***
	 * 获取客户端ip的国家代码
	 * @param routingContext
	 * @return
	 */
	public static String getIpCountry(RoutingContext routingContext){
		return Tool.getIpCountry(routingContext);
	}

	/***
	 * 发送收据到app验证
	 * @param webClient
	 * @param isSandBox
	 * @param receipt
	 * @return
	 */
	public static Future<JsonObject> checkAppReceipt(WebClient webClient,boolean isSandBox,String  receipt) {
		Promise<JsonObject> fut = Promise.promise();
		String urlstr;
		if(isSandBox){
			urlstr = "https://sandbox.itunes.apple.com/verifyReceipt";
		}else{
			urlstr = "https://buy.itunes.apple.com/verifyReceipt";
		}
		JsonObject obj  = new JsonObject().put("receipt-data", receipt);
		webClient.postAbs(urlstr).timeout(30000).sendJson(obj, res->{
			if(res.succeeded()){
				HttpResponse<Buffer> response = res.result();
				int code = response.statusCode();
				JsonObject resObj = response.bodyAsJsonObject();
//				logger.info("#### receive checkAppReceipt httpCode:"+code+" response:"+response.bodyAsString());
				fut.complete(resObj);
			}else{
				logger.error(res.cause().getMessage());
				res.cause().printStackTrace();
				fut.fail(res.cause().getMessage());
			}
		});
		return fut.future();
	}

	/**
	 * 通过gm@mo发送邮件
	 * @param toAddress
	 * @param message
	 */
	public static void sendEmail(String toAddress, String message) {

	}
	
	/***
	 * 搜索数据，旧接口
	 * @param routingContext
	 * @param jdbcClient
	 * @param tableName
	 * @param sql1
	 * @param params1
	 * @param sql2
	 * @param params2
	 */
	public static void searchFromTable(RoutingContext routingContext,SQLClient jdbcClient,String tableName,String sql1,JsonArray params1,String sql2,JsonArray params2){

//		logger.info("searchFromTable  sql1:"+sql1 +" param1:"+params1.toString());
//		logger.info("searchFromTable  sql2:"+sql2 +" param2:"+params2.toString());
		HttpServerResponse response = routingContext.response();


		Promise<JsonArray> futn=Promise.promise(); //定义最终的操作
		Promise<JsonArray> fut1 = Promise.promise();//定义第一个操作
		JsonObject result = new JsonObject();
		long startTime = System.currentTimeMillis();
		//使用compose示例 串行方式
		//		MysqlTool.queryJsonArrayFromDb(jdbcClient, sql1,params1,fut1.completer());//执行第一个查询

		//		fut1.compose(handler1-> {	
		//			logger.info("search "+(System.currentTimeMillis()-startTime)+"ms sql1:"+sql1 +" param1:"+params1.toString());
		//			int total = handler1.getJsonObject(0).getInteger("count(1)");
		//			result.put("total", total);
		//			if(total > 0){
		//				MysqlTool.queryJsonArrayFromDb(jdbcClient, sql2,params2, futn);//执行第二个查询
		//			}else{//如果第一个查询没有结果，则不需要再子查询
		//				futn.complete(new JsonArray());
		//			}
		//
		//		},futn);
		//
		//		futn.onComplete(handler->{//设置最终处理函数
		//			logger.info("search "+(System.currentTimeMillis()-startTime)+"ms sql2:"+sql2 +" param2:"+params2.toString());
		//			if(handler.succeeded() && handler.result() != null){
		//				JsonArray list = handler.result();
		//				result.put("rows",list);
		//				sendHttpResponse(response, result);
		//			}else{
		//				sendHttpResponseError(response,  handler.cause().getMessage());
		//			}
		//		});
		routingContext.vertx().executeBlocking(()->{
			//使用compose示例 并行方式
			PostgreUtils.queryJsonArrayFromDb(jdbcClient, sql1,params1,fut1);//执行第一个查询
			PostgreUtils.queryJsonArrayFromDb(jdbcClient, sql2,params2, futn);//执行第二个查询
			Future.all(fut1.future(),futn.future()).onComplete(res->{
				if(res.succeeded()) {
					int queryTime = (int)(System.currentTimeMillis()-startTime)/1000;
									
					int total = fut1.future().result().getJsonObject(0).getInteger("count(1)");
					result.put("total", total);
					JsonArray list = futn.future().result();
					result.put("rows",list);
					sendHttpResponse(response, result);
					if(queryTime >= 10 && tableName.startsWith("record_")) {//大于10秒的查询，打印一下
						recordQueryLongTime(jdbcClient, sql1, params1, sql2, params2, queryTime);
					}
				}else {
					sendHttpResponseError(response,  res.cause().getMessage());
					logger.error("####### searchFromTable error:"+res.cause().getMessage());
				}
//				ft.complete();
			});
			return null;
		}, false, r -> {
			if (r.failed()) {
				logger.error("####### searchFromTable executeBlocking error:" + r.cause().getMessage());
			}
//			logger.info("####### searchFromTable complete time:"+(System.currentTimeMillis()-startTime)+"ms");
		});

	}
	
	public static void recordQueryLongTime(SQLClient jdbcClient,String sql1,JsonArray params1,String sql2,JsonArray params2,int queryTime) {
		String sql = "insert into log_query(sql1,params1,sql1_final,sql2,params2,sql2_final,querytime,addtime) values(?,?,?,?,?,?,?,?);";
		JsonArray params = new JsonArray();
		params.add(sql1);
		params.add(params1.toString());
		params.add(Tool.getSqlString(sql1, params1));
		params.add(sql2);
		params.add(params2.toString());
		params.add(Tool.getSqlString(sql2, params2));
		params.add(queryTime);
		params.add(TimeUtils.getCurTime());
		PostgreUtils.updateToDb(jdbcClient, sql, params, handler->{});
	}
	/***
	 * 根据搜索条件列表，从表中搜索数据
	 * @param routingContext 
	 * @param jdbcClient
	 * @param json 客户端上行数据
	 * @param tableName 表名
	 * @param scList 搜索条件列表
	 */
	protected static void searchFromTable(RoutingContext routingContext,SQLClient jdbcClient,JsonObject json,String tableName,List<SearchCondition> scList){

		String sql1 = " FROM "+tableName+" where 1=1 ";
		JsonArray params1 = new JsonArray();
		String str1 = getSearchString(scList, json, params1);
		String sortColumn = "id desc";//默认按id排序
		if(json.containsKey("orderby")){
			sortColumn = json.getString("orderby");
		}
		sql1 += str1+" order by "+sortColumn;

		String sql = "select count(1) "+sql1+";";
		String columns = "*";
		if(json.containsKey("columns")){
			columns = getColumnsString(json.getJsonArray("columns"));

		}
		String sql2 = "select "+columns+" "+sql1+" limit ?,?; ";
		JsonArray params2 = params1.copy();
		int pageNo = json.getInteger("pageNo");
		int pageSize = json.getInteger("pageSize");
		int start = pageNo*pageSize;
		params2.add(start);
		params2.add(pageSize);
		searchFromTable(routingContext,jdbcClient, tableName, sql, params1, sql2, params2);
	}

	/**
	 * web后台校验授权码
	 * @param routingContext
	 * @param jdbcClientWeb
	 * @param code
	 * @return
	 */
	public static Boolean checkCodeByWebInfo(RoutingContext routingContext,Pool jdbcClientWeb,int webId,String code){
		boolean result = false;
		try {
			String sql = "SELECT * FROM webtype where id = ?;";
			JsonArray params = new JsonArray().add(webId);
			Promise<JsonObject> queryPromise = Promise.promise();
			MysqlTool.queryJsonObjectFromDb(jdbcClientWeb, sql, params,queryPromise);
			JsonObject webInfo = Future.await(queryPromise.future());
			if (webInfo == null ){
				sendHttpResponseError(routingContext.response(), "ServerParam webid 配置错误!!!");
				return result;

			}
			if (webInfo.getInteger("isgameserver") == 2) {
				//正式服需要校验授权码
				String webCode = webInfo.getString("name") + "-" + webInfo.getString("ip");
				if (!webCode.equals(code)) {
					sendHttpResponseError(routingContext.response(), "请输入正确的授权码!");
					return result;
				}
			}
			result = true;
			return result;
		} catch (Exception e) {
			logger.error("checkCodeByWebInfo erorr:"+ Tool.getException(e));
			sendHttpResponseError(routingContext.response(), e.getMessage());
			return result;
		}
	}
}
